﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NUnit.Framework;
using Extjs_ReGSharpTest.Stubs;
using Extjs_ReGSharp;
using System.Collections.Specialized;
using Extjs_ReGSharpTest.SortingBehaviour;

namespace Extjs_ReGSharpTest
{
	[TestFixture]
	public class UserRequestExecuterTests
	{
		#region Data Members

		private DataObjectStub m_LowerObject;
		private DataObjectStub m_GreaterObject;

		private GridSource<DataObjectStub> m_AscendingOrderedGridSource;
		private UserRequestExecuter<DataObjectStub> m_AscendingOrderedExecuter;

		private GridSource<DataObjectStub> m_DescendingOrderedGridSource;
		private UserRequestExecuter<DataObjectStub> m_DescendingOrderedExecuter;

		#endregion

		#region Private Methods

		private void InitializeGridSources()
		{
			DateTime septemberTheFirst2010 = new DateTime(2010, 9, 1);
			DateTime septemberTheSecond2010 = septemberTheFirst2010 + TimeSpan.FromDays(1);

			m_LowerObject = new DataObjectStub(0, "a", false, septemberTheFirst2010);
			m_GreaterObject = new DataObjectStub(1, "b", true, septemberTheSecond2010);

			m_AscendingOrderedGridSource = new GridSource<DataObjectStub>(new List<DataObjectStub>(new DataObjectStub[] { m_LowerObject, m_GreaterObject }));
			m_DescendingOrderedGridSource = new GridSource<DataObjectStub>(new List<DataObjectStub>(new DataObjectStub[] { m_GreaterObject, m_LowerObject }));
		}

		private void InitializeUserRequestExecuters()
		{
			m_AscendingOrderedExecuter = new UserRequestExecuter<DataObjectStub>(m_AscendingOrderedGridSource);
			m_DescendingOrderedExecuter = new UserRequestExecuter<DataObjectStub>(m_DescendingOrderedGridSource);
		}

		#endregion

		#region Setup

		[SetUp]
		public void Initialize()
		{
			InitializeGridSources();
			InitializeUserRequestExecuters();
		}

		#endregion

		#region Tests

		#region Paging Tests

		[Test]
		public void SourceItems_WhenUserRequestExecuterIsCreatedWithGridSourceThatContainsAListOfItems_TheSourceItemsReturnedAreEqualsToTheOriginalGridSourceList()
		{
			CollectionAssert.AreEqual(m_AscendingOrderedExecuter.SourceItems, m_AscendingOrderedGridSource.SourceItems);
		}

		[Test]
		public void GetItemsByRequestParameters_OnRequestForPageThatCanFitAllOfTwoItemsOnTheSource_TheResultItemsCountIsTwo()
		{
			NameValueCollection input = (new InputBuilder()).AddPagingParameters(0, 100).Build();

			GridResult<DataObjectStub> result = m_AscendingOrderedExecuter.GetItemsByRequestParameters(input);

			Assert.AreEqual(result.topics.Count, 2);
		}

		[Test]
		public void GetItemsByRequestParameters_OnRequestForPageThatCanFitTwoOfTheItemsOnTheSource_TheResultItemsTotalCountIsTwo()
		{
			NameValueCollection input = (new InputBuilder()).AddPagingParameters(0, 100).Build();

			GridResult<DataObjectStub> result = m_AscendingOrderedExecuter.GetItemsByRequestParameters(input);

			Assert.AreEqual(int.Parse(result.totalCount), 2);
		}

		[Test]
		public void GetItemsByRequestParameters_OnRequestForPageWithOneItemOnlyFromIndex0_TheResultItemsCountIsOne()
		{
			NameValueCollection input = (new InputBuilder()).AddPagingParameters(0, 1).Build();

			GridResult<DataObjectStub> result = m_AscendingOrderedExecuter.GetItemsByRequestParameters(input);

			Assert.AreEqual(result.topics.Count, 1);
		}

		[Test]
		public void GetItemsByRequestParameters_OnRequestForPageWithOneItemOnlyFromIndex0_TheResultItemsTotalCountIsTheAmountOfAllOfTheSourceItems()
		{
			NameValueCollection input = (new InputBuilder()).AddPagingParameters(0, 1).Build();

			GridResult<DataObjectStub> result = m_AscendingOrderedExecuter.GetItemsByRequestParameters(input);

			Assert.AreEqual(int.Parse(result.totalCount), 2);
		}

		[Test]
		public void GetItemsByRequestParameters_OnRequestForPageWithOneItemOnlyFromIndex1_TheResultItemsCountIsOne()
		{
			NameValueCollection input = (new InputBuilder()).AddPagingParameters(1, 1).Build();

			GridResult<DataObjectStub> result = m_AscendingOrderedExecuter.GetItemsByRequestParameters(input);

			Assert.AreEqual(result.topics.Count, 1);
		}

		[Test]
		public void GetItemsByRequestParameters_OnRequestForPageWithOneItemOnlyFromIndex1_TheResultItemsTotalCountIsTheAmountOfAllOfTheSourceItems()
		{
			NameValueCollection input = (new InputBuilder()).AddPagingParameters(1, 1).Build();

			GridResult<DataObjectStub> result = m_AscendingOrderedExecuter.GetItemsByRequestParameters(input);

			Assert.AreEqual(int.Parse(result.totalCount), 2);
		}

		#endregion

		#region Sorting Tests

		[Test]
		public void GetItemsByRequestParameters_OnRequestForSortingTheObjectByIntegerFieldWithoutSpecifyingDirection_TheResultItemsListIsInAnAscendingOrderByTheIntField()
		{
			NameValueCollection input = (new InputBuilder()).
				AddPagingParameters(0, 100).
				AddSortingParameters("IntField", string.Empty).
				Build();

			GridResult<DataObjectStub> result = m_DescendingOrderedExecuter.GetItemsByRequestParameters(input);

			CollectionAssert.AreEqual(result.topics, m_AscendingOrderedGridSource.SourceItems);
		}

		[Test]
		public void GetItemsByRequestParameters_OnRequestForSortingTheObjectByIntegerFieldAscending_TheResultItemsListIsInAnAscendingOrderByTheIntField()
		{
			NameValueCollection input = (new InputBuilder()).
				AddPagingParameters(0, 100).
				AddSortingParameters("IntField", "asc").
				Build();

			GridResult<DataObjectStub> result = m_DescendingOrderedExecuter.GetItemsByRequestParameters(input);

			CollectionAssert.AreEqual(result.topics, m_AscendingOrderedGridSource.SourceItems);
		}

		[Test]
		public void GetItemsByRequestParameters_OnRequestForSortingTheObjectByIntegerFieldDescending_TheResultItemsListIsInADescendingOrderByTheIntField()
		{
			NameValueCollection input = (new InputBuilder()).
				AddPagingParameters(0, 100).
				AddSortingParameters("IntField", "desc").
				Build();

			GridResult<DataObjectStub> result = m_AscendingOrderedExecuter.GetItemsByRequestParameters(input);

			CollectionAssert.AreEqual(result.topics, m_DescendingOrderedExecuter.SourceItems);
		}

		[Test]
		public void GetItemsByRequestParameters_OnRequestForSortingTheObjectByBooleanFieldAscending_TheResultItemsListIsInAnAscendingOrderByTheBooleanField()
		{
			NameValueCollection input = (new InputBuilder()).
				AddPagingParameters(0, 100).
				AddSortingParameters("BoolField", "asc").
				Build();

			GridResult<DataObjectStub> result = m_DescendingOrderedExecuter.GetItemsByRequestParameters(input);

			CollectionAssert.AreEqual(result.topics, m_AscendingOrderedGridSource.SourceItems);
		}

		[Test]
		public void GetItemsByRequestParameters_OnRequestForSortingTheObjectByBooleanFieldDescending_TheResultItemsListIsInADescendingOrderByTheBooleanField()
		{
			NameValueCollection input = (new InputBuilder()).
				AddPagingParameters(0, 100).
				AddSortingParameters("BoolField", "desc").
				Build();

			GridResult<DataObjectStub> result = m_AscendingOrderedExecuter.GetItemsByRequestParameters(input);

			CollectionAssert.AreEqual(result.topics, m_DescendingOrderedExecuter.SourceItems);
		}

		[Test]
		public void GetItemsByRequestParameters_OnRequestForSortingTheObjectByStringFieldAscending_TheResultItemsListIsInAnAscendingOrderByTheStringField()
		{
			NameValueCollection input = (new InputBuilder()).
				AddPagingParameters(0, 100).
				AddSortingParameters("StringField", "asc").
				Build();

			GridResult<DataObjectStub> result = m_DescendingOrderedExecuter.GetItemsByRequestParameters(input);

			CollectionAssert.AreEqual(result.topics, m_AscendingOrderedGridSource.SourceItems);
		}

		[Test]
		public void GetItemsByRequestParameters_OnRequestForSortingTheObjectByStringFieldDescending_TheResultItemsListIsInADescendingOrderByTheStringField()
		{
			NameValueCollection input = (new InputBuilder()).
				AddPagingParameters(0, 100).
				AddSortingParameters("StringField", "desc").
				Build();

			GridResult<DataObjectStub> result = m_AscendingOrderedExecuter.GetItemsByRequestParameters(input);

			CollectionAssert.AreEqual(result.topics, m_DescendingOrderedExecuter.SourceItems);
		}

		[Test]
		public void GetItemsByRequestParameters_OnRequestForSortingTheObjectByDateTimeFieldAscending_TheResultItemsListIsInAnAscendingOrderByTheDateTimeField()
		{
			NameValueCollection input = (new InputBuilder()).
				AddPagingParameters(0, 100).
				AddSortingParameters("DateTimeField", "asc").
				Build();

			GridResult<DataObjectStub> result = m_DescendingOrderedExecuter.GetItemsByRequestParameters(input);

			CollectionAssert.AreEqual(result.topics, m_AscendingOrderedGridSource.SourceItems);
		}

		[Test]
		public void GetItemsByRequestParameters_OnRequestForSortingTheObjectByDateTimeFieldDescending_TheResultItemsListIsInADescendingOrderByTheDateTimeField()
		{
			NameValueCollection input = (new InputBuilder()).
				AddPagingParameters(0, 100).
				AddSortingParameters("DateTimeField", "desc").
				Build();

			GridResult<DataObjectStub> result = m_AscendingOrderedExecuter.GetItemsByRequestParameters(input);

			CollectionAssert.AreEqual(result.topics, m_DescendingOrderedExecuter.SourceItems);
		}

		[Test]
		public void GetItemsByRequestParameters_OnCustomSortingBehaviourRegisteredForTheIntFieldAndSortingByThatField_TheCustomSortingBehaviourIsTheBehaviourThatWasActiveForTheResult()
		{
			NameValueCollection input = (new InputBuilder()).
				AddPagingParameters(0, 100).
				AddSortingParameters("IntField", "asc").
				Build();

			m_DescendingOrderedExecuter.RegisterSortBehaviour(new OppositeOrderSortingBehaviourFactory());

			GridResult<DataObjectStub> result = m_DescendingOrderedExecuter.GetItemsByRequestParameters(input);

			CollectionAssert.AreEqual(result.topics, m_DescendingOrderedGridSource.SourceItems);
		}

		#endregion

		#region Filtering Tests

		[Test]
		public void GetItemsByRequestParameters_OnNumericFieldGeaterThanANumberFilteringThatShouldFilterOneOfTheTwoSourceObjects_TheResultTotalCountIs1()
		{
			NameValueCollection input = (new InputBuilder()).
				AddPagingParameters(0, 100).
				AddFilteringParameter("IntField", "numeric", "gt", "0").
				Build();

			GridResult<DataObjectStub> result = m_AscendingOrderedExecuter.GetItemsByRequestParameters(input);

			Assert.AreEqual(int.Parse(result.totalCount), 1);
		}

		[Test]
		public void GetItemsByRequestParameters_OnNumericFieldGeaterThanANumberFilteringThatShouldFilterOneOfTheTwoSourceObjects_TheResultItemsCountIs1()
		{
			NameValueCollection input = (new InputBuilder()).
				AddPagingParameters(0, 100).
				AddFilteringParameter("IntField", "numeric", "gt", "0").
				Build();

			GridResult<DataObjectStub> result = m_AscendingOrderedExecuter.GetItemsByRequestParameters(input);

			Assert.AreEqual(result.topics.Count, 1);
		}

		[Test]
		public void GetItemsByRequestParameters_OnNumericFieldGeaterThanANumberFilteringThatShouldFilterOneOfTheTwoSourceObjects_TheResultItemsListContainsTheObjectThatShouldntBeFiltered()
		{
			NameValueCollection input = (new InputBuilder()).
				AddPagingParameters(0, 100).
				AddFilteringParameter("IntField", "numeric", "gt", "0").
				Build();

			GridResult<DataObjectStub> result = m_AscendingOrderedExecuter.GetItemsByRequestParameters(input);

			Assert.AreEqual(result.topics[0], m_GreaterObject);
		}

		[Test]
		public void GetItemsByRequestParameters_OnNumericFieldLowerThanANumberFilteringThatShouldFilterOneOfTheTwoSourceObjects_TheResultTotalCountIs1()
		{
			NameValueCollection input = (new InputBuilder()).
				AddPagingParameters(0, 100).
				AddFilteringParameter("IntField", "numeric", "lt", "1").
				Build();

			GridResult<DataObjectStub> result = m_AscendingOrderedExecuter.GetItemsByRequestParameters(input);

			Assert.AreEqual(int.Parse(result.totalCount), 1);
		}

		[Test]
		public void GetItemsByRequestParameters_OnNumericFieldLowerThanANumberFilteringThatShouldFilterOneOfTheTwoSourceObjects_TheResultItemsCountIs1()
		{
			NameValueCollection input = (new InputBuilder()).
				AddPagingParameters(0, 100).
				AddFilteringParameter("IntField", "numeric", "lt", "1").
				Build();

			GridResult<DataObjectStub> result = m_AscendingOrderedExecuter.GetItemsByRequestParameters(input);

			Assert.AreEqual(result.topics.Count, 1);
		}

		[Test]
		public void GetItemsByRequestParameters_OnNumericFieldLowerThanANumberFilteringThatShouldFilterOneOfTheTwoSourceObjects_TheResultItemsListContainsTheObjectThatShouldntBeFiltered()
		{
			NameValueCollection input = (new InputBuilder()).
				AddPagingParameters(0, 100).
				AddFilteringParameter("IntField", "numeric", "lt", "1").
				Build();

			GridResult<DataObjectStub> result = m_AscendingOrderedExecuter.GetItemsByRequestParameters(input);

			Assert.AreEqual(result.topics[0], m_LowerObject);
		}

		[Test]
		public void GetItemsByRequestParameters_OnNumericFieldEqualsToANumberFilteringThatShouldFilterOneOfTheTwoSourceObjects_TheResultTotalCountIs1()
		{
			NameValueCollection input = (new InputBuilder()).
				AddPagingParameters(0, 100).
				AddFilteringParameter("IntField", "numeric", "eq", "1").
				Build();

			GridResult<DataObjectStub> result = m_AscendingOrderedExecuter.GetItemsByRequestParameters(input);

			Assert.AreEqual(int.Parse(result.totalCount), 1);
		}

		[Test]
		public void GetItemsByRequestParameters_OnNumericFieldEqualsToANumberFilteringThatShouldFilterOneOfTheTwoSourceObjects_TheResultItemsCountIs1()
		{
			NameValueCollection input = (new InputBuilder()).
				AddPagingParameters(0, 100).
				AddFilteringParameter("IntField", "numeric", "eq", "1").
				Build();

			GridResult<DataObjectStub> result = m_AscendingOrderedExecuter.GetItemsByRequestParameters(input);

			Assert.AreEqual(result.topics.Count, 1);
		}

		[Test]
		public void GetItemsByRequestParameters_OnNumericFieldEqualsToANumberFilteringThatShouldFilterOneOfTheTwoSourceObjects_TheResultItemsListContainsTheObjectThatShouldntBeFiltered()
		{
			NameValueCollection input = (new InputBuilder()).
				AddPagingParameters(0, 100).
				AddFilteringParameter("IntField", "numeric", "eq", "1").
				Build();

			GridResult<DataObjectStub> result = m_AscendingOrderedExecuter.GetItemsByRequestParameters(input);

			Assert.AreEqual(result.topics[0], m_GreaterObject);
		}

		[Test]
		public void GetItemsByRequestParameters_OnStringFieldStartingWithFilteringThatShouldFilterOneOfTheTwoSourceObjects_TheResultTotalCountIs1()
		{
			NameValueCollection input = (new InputBuilder()).
				AddPagingParameters(0, 100).
				AddFilteringParameter("StringField", "string", "", "a").
				Build();

			GridResult<DataObjectStub> result = m_AscendingOrderedExecuter.GetItemsByRequestParameters(input);

			Assert.AreEqual(int.Parse(result.totalCount), 1);
		}

		[Test]
		public void GetItemsByRequestParameters_OnStringFieldStartingWithFilteringThatShouldFilterOneOfTheTwoSourceObjects_TheResultItemsCountIs1()
		{
			NameValueCollection input = (new InputBuilder()).
				AddPagingParameters(0, 100).
				AddFilteringParameter("StringField", "string", "", "a").
				Build();

			GridResult<DataObjectStub> result = m_AscendingOrderedExecuter.GetItemsByRequestParameters(input);

			Assert.AreEqual(result.topics.Count, 1);
		}

		[Test]
		public void GetItemsByRequestParameters_OnStringFieldStartingWithFilteringThatShouldFilterOneOfTheTwoSourceObjects_TheResultItemsListContainsTheObjectThatShouldntBeFiltered()
		{
			NameValueCollection input = (new InputBuilder()).
				AddPagingParameters(0, 100).
				AddFilteringParameter("StringField", "string", "", "a").
				Build();

			GridResult<DataObjectStub> result = m_AscendingOrderedExecuter.GetItemsByRequestParameters(input);

			Assert.AreEqual(result.topics[0], m_LowerObject);
		}

		[Test]
		public void GetItemsByRequestParameters_WhenFilteringWithTwoCriteriaThatTheFirstCriteriaFiltersOneItemAndTheOtherCriteriaFiltersTheOtherItemOutOfTheTwo_TheResultItemListIsEmpty()
		{
			NameValueCollection input = (new InputBuilder()).
				AddPagingParameters(0, 100).
				AddFilteringParameter("StringField", "string", "", "a").
				AddFilteringParameter("IntField", "numeric", "gt", "0").
				Build();

			GridResult<DataObjectStub> result = m_AscendingOrderedExecuter.GetItemsByRequestParameters(input);

			Assert.AreEqual(result.topics.Count, 0);
		}

		[Test]
		public void GetItemsByRequestParameters_WhenFilteringWithTwoCriteriaThatTheFirstCriteriaFiltersOneItemAndTheOtherCriteriaFiltersTheOtherItemOutOfTheTwo_TheResultItemTotalCountIsZero()
		{
			NameValueCollection input = (new InputBuilder()).
				AddPagingParameters(0, 100).
				AddFilteringParameter("StringField", "string", "", "a").
				AddFilteringParameter("IntField", "numeric", "gt", "0").
				Build();

			GridResult<DataObjectStub> result = m_AscendingOrderedExecuter.GetItemsByRequestParameters(input);

			Assert.AreEqual(int.Parse(result.totalCount), 0);
		}

		#endregion

		#endregion
	}
}
